/**
	Pulsar engine. Additional include file.
	Base application class (MS Windows).

	Copyright (C) 2013-2014 Dmitry Dolgov

	This program is free software; you can redistribute it and/or modify it under the terms of the
	GNU General Public License as published by the Free Software Foundation; either version 2 of
	the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.
*/

#if !defined(PL_WINDOWS) && !defined(PL_WINDOWS64)
#error "Wrong Operation System"
#endif

namespace pl
{

/*
	setDebugWindows() options mask
*/
const pl_uint32 DEBUG_WINDOW_ASSERT      = 0x00000001; /// Show Windows Assertion failed dialog box
const pl_uint32 DEBUG_WINDOW_MEMERR      = 0x00000002; /// Show Memory error dialog box
const pl_uint32 DEBUG_WINDOW_OUTMEM      = 0x00000004; /// Show Out of memory dialog box
const pl_uint32 DEBUG_WINDOW_FATAL_ERR   = 0x00000008; /// Show Fatal Error dialog box

/*
	setCommonControls() options
*/

const pl_uint32 COMMON_CONTROLS_ANIMATE_CLASS      = 0x00000001; // The same as ICC_ANIMATE_CLASS
const pl_uint32 COMMON_CONTROLS_BAR_CLASSES	       = 0x00000002; // The same as ICC_BAR_CLASSES
const pl_uint32 COMMON_CONTROLS_COOL_CLASSES       = 0x00000004; // The same as ICC_COOL_CLASSES
const pl_uint32 COMMON_CONTROLS_DATE_CLASSES       = 0x00000008; // The same as ICC_DATE_CLASSES
const pl_uint32 COMMON_CONTROLS_HOTKEY_CLASS       = 0x00000010; // The same as ICC_HOTKEY_CLASS
const pl_uint32 COMMON_CONTROLS_INTERNET_CLASSES   = 0x00000020; // The same as ICC_INTERNET_CLASSES
const pl_uint32 COMMON_CONTROLS_LINK_CLASS         = 0x00000040; // The same as ICC_LINK_CLASS
const pl_uint32 COMMON_CONTROLS_LISTVIEW_CLASSES   = 0x00000080; // The same as ICC_LISTVIEW_CLASSES
const pl_uint32 COMMON_CONTROLS_NATIVEFNTCTL_CLASS = 0x00000100; // The same as ICC_NATIVEFNTCTL_CLASS
const pl_uint32 COMMON_CONTROLS_PAGESCROLLER_CLASS = 0x00000200; // The same as ICC_PAGESCROLLER_CLASS
const pl_uint32 COMMON_CONTROLS_PROGRESS_CLASS     = 0x00000400; // The same as ICC_PROGRESS_CLASS
const pl_uint32 COMMON_CONTROLS_STANDARD_CLASSES   = 0x00000800; // The same as ICC_STANDARD_CLASSES (set by default)
const pl_uint32 COMMON_CONTROLS_TAB_CLASSES        = 0x00001000; // The same as ICC_TAB_CLASSES
const pl_uint32 COMMON_CONTROLS_TREEVIEW_CLASSES   = 0x00002000; // The same as ICC_TREEVIEW_CLASSES
const pl_uint32 COMMON_CONTROLS_UPDOWN_CLASS       = 0x00004000; // The same as ICC_UPDOWN_CLASS
const pl_uint32 COMMON_CONTROLS_USEREX_CLASSES     = 0x00008000; // The same as ICC_USEREX_CLASSES
const pl_uint32 COMMON_CONTROLS_WIN95_CLASSES      = 0x00010000; // The same as ICC_WIN95_CLASSES (set by default)
const pl_uint32 COMMON_CONTROLS_ALL_CLASSES        = 0x0001FFFF; // All InitCommonCOntrolsEx() classes
const pl_uint32 COMMON_CONTROLS_RICHEDIT2          = 0x00020008; // Load richedit 2.0 library

struct ExceptionInfo
{
	// TODO
};

/*
	Advances Startup initialization for Windows applications
*/
class StartupFunc : public StartupFuncBase
{
public:
	/// Allows to show debugging windows
	void setDebugWindows(pl_uint32 windowMask);

	/// Set common controls
	void setCommonControls(pl_uint32 commonControls);

	/// Set unhandled exception filter
	void registerExceptionFilter();
};

/*
*/
class App : public AppBase
{
public:
	static App* app;

	/// Register main class and create main window
	static bool createMainClass(const pl_char* className, DWORD classStyle, HICON hIcon, HCURSOR hCursor, HBRUSH hBrush, const pl_char* pMenuName, DWORD windowStyle, const RECT& rectWnd, DWORD exStyle = 0);

	/// Set custom main window
	static void setHMainWindow(HWND hWindow);

	/// Translate messages from main loop
	static void dispatch(::MSG* msg);

	/// Get HINSTANCE of the current app
	inline HINSTANCE getHInstance()
	{
		return _hInstance;
	}

	/// Get main window handle
	static HWND getHMainWindow();


#if defined(PL_ENTRY_POINT_EXTERNAL)

	virtual StartupFunc& getBaseSettings(); // Can be used before init() only!!!
	virtual bool init(int argc, const pl_char* argv[]);
	virtual bool init(const pl_char* cmdLine);
	virtual void term();

#elif defined(PL_ENTRY_POINT_INTERNAL)

#if defined(PL_DOS)
	int _main(int argc, const char* argv[]); // Console version (PL_DOS) - internal usage only
#elif defined (PL_DLL)
	int _dllMain(HANDLE hInstance, DWORD dwReason); // Windows DLL - internal usage only
	void onProcessAttach();
	void onThreadAttach();
	void onThreadDetach();
	void onProcessDetach();
#else
	int _winMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); // Standard Windows version (PL_WINDOWS) - internal usage only
#endif

#else

#error "Unknown entry point mode"

#endif

	// Get standard path
	virtual const Filepath& getStdPath(StarndardPath path);

	// Get computer name
	virtual const String64& getComputerName()
	{
		return _compName;
	}

	// Get current language
	virtual pl::String32 getCurrentLanguage()
	{
		return _langName;
	}

	/// Get current date and time
	virtual bool getCurDateTime(DateTime& dateTime);

	virtual void terminateProcess(int exitCode);

	virtual void _onTrace(const pl_char* file, pl_uint32 line, const pl_char* msg);
	virtual HandleResult _onAssert(const pl_char* file, pl_uint32 line, const pl_char* func, const pl_char* cond, const pl_char* msg, pl::AssertType type);
	virtual HandleResult _onMemErr(const pl_char* file, pl_uint32 line, const pl_char* func, void* p, pl_int64 size, pl::MemoryError idEvent);


protected:
	App();
	virtual ~App();

private:
	HINSTANCE _hInstance;

	pl::Filepath _appRootFolder;
	pl::Filepath _exeNameFolder;
	pl::Filepath _systemFolder;
	pl::Filepath _programsFolder;
	pl::Filepath _userHomeFolder;
	pl::Filepath _documentsFolder;
	pl::Filepath _settingsFolder;
	pl::Filepath _tempFolder;
	String64 _compName;
	String32 _langName;

	void _initWin();
	void _termWin();

	static LRESULT WINAPI _mainWndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
};


} // namespace pl

//
// End of file 'pulsar_app_win.h'
//
